#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "MSTK.h"

#ifdef __cplusplus
extern "C" {
#endif

extern  MPI_Datatype PVertex_MPI,PFace_MPI;

int MESH_Surf_RecvMesh(Mesh_ptr mesh, int rank, MPI_Comm comm) {
  int i, j, k, idx, nfv;
  int nv, nf;
  MVertex_ptr *verts, *fverts;
  MFace_ptr mf;
  
  /* basic mesh information */
  nv = 10000;
  nf = 20000;
  /* construct derived datatype */
  /*
  MPI_Datatype PVertex_MPI,PFace_MPI;
  MPI_Aint extent;
  MPI_Type_extent(MPI_DOUBLE,&extent);
  int counts[2] = {3,3};
  MPI_Aint offsets[2];
  offsets[0] = 0; offsets[1] = 3*extent;
  MPI_Datatype types[2] = {MPI_DOUBLE,MPI_INT};
  MPI_Type_create_struct(2,counts,offsets,types,&PVertex_MPI);
  MPI_Type_contiguous(12,MPI_INT,&PFace_MPI);
  */
  printf("PVertex_MPI datatype established\n");
  /* end construct derived datatype */
  
  PVertex *list_vertex = (PVertex *)MSTK_malloc(nv*sizeof(PVertex));
  PFace *list_face = (PFace *)MSTK_malloc(nf*sizeof(PFace));

  MPI_Status status;
  int count;
  printf("MPI_Recv vertex started %d\n",rank);
  MPI_Recv(list_vertex,nv,PVertex_MPI,0,rank,comm,&status);
  printf("MPI_Recv vertex finished %d\n",rank);
  MPI_Get_count(&status,PVertex_MPI,&count);
  printf("num of vertex received %d\n",count);

  verts = (MVertex_ptr *) malloc(nv*sizeof(MVertex_ptr));
  for(i = 0; i < count; i++) {
    verts[i] = MV_New(mesh);
    PV_to_MV(&list_vertex[i],verts[i]);
    MV_Set_ID(verts[i],i+1);
  }


  printf("MPI_Recv face started %d\n",rank);
  MPI_Recv(list_face,nf,PFace_MPI,0,100+rank,comm,&status);
  printf("MPI_Recv face finished %d\n",rank);
  MPI_Get_count(&status,PFace_MPI,&count);
  printf("num of face received %d\n",count);

  fverts = (MVertex_ptr *) malloc(9*sizeof(MVertex_ptr));
  for (i = 0; i < count; i++) {
    mf = MF_New(mesh);
    nfv = (list_face[i].gid_gdim_nfv) & 31;
    PF_to_MF(&list_face[i],mf);
    for (j = 0; j < nfv; j++) {
      fverts[j] = verts[list_face[i].vids[j]-1];
    }
    MF_Set_Vertices(mf,nfv,fverts);
    MF_Set_ID(mf,i+1);
  }
  if (fverts) free(fverts);

  PMESH_WriteToFile(mesh,"parallel.mstk",F1);
  fprintf(stdout,"parallel mesh %d has been written\n",rank);

  if (verts) free(verts);
  MSTK_free(list_vertex);    
  MSTK_free(list_face);    
  return 1;
}
  
#ifdef __cplusplus
}
#endif

